
/**
 * @class Kohive.app.VideosController
 * @extends ExtMVC.Controller
 * Manages the VideoAlbum and Video models, renders the Videos main view and emits events when
 * VideoAlbum and Video changes are made
 */
Kohive.app.VideosController = Ext.extend(Kohive.controllers.KohiveController, {
	name			: 'videos',

	currentAlbum	: {},

	constructor		: function() {
		Kohive.app.VideosController.superclass.constructor.call(this, {
					viewsPackage	: Kohive.views.videos
				});

		this.initEvents();
		this.initListeners();

		// TODO: This is a relic of old MVC, remove it once on ExtMVC 0.6 or above
		this.registerAction('index', this.index);
		this.registerAction('create', this.create);
	},

	/**
	 * @action index 
	 * Renders the index view
	 */
	index			: function() {
		this.indexWindow = this.renderView('index', {
					albumStore	: Kohive.models.VideoAlbum.findAll({
								url	: this.scopedUrl('video_albums')
							}),
					closeAction	: 'hide',
					autoShow	: true,
					listeners	: {
						scope			: this,
						'load-album'	: this.loadAlbumVideos,
						'refresh'		: this.loadAlbumVideos.createDelegate(
								this, [null, null, true]
						),
						'filter'		: this.filter,
						'show-video'	: this.show,
						'update-video'	: this.update,
						'destroy-video'	: this.destroy,
						'destroy-album'	: this.destroyAlbum,
						'create-album'	: this.createAlbum
						// 'create-rss-album' : this.createRssAlbum
					}
				});

		this.indexWindow.show();

		this.fireEvent('index');
	},

	/**
	 * @action update
	 * Updates the given video with the provided arguments
	 * @param {Kohive.models.Video} video The video to update
	 * @param {Object} fields An object containing keys and values to update
	 */
	update			: function(video, fields) {
		this.fireEvent('before-update');

		for (var key in fields) {
			video.set(key, fields[key]);
		};

		// update the tags array - ideally we wouldn't do this here, should be in the model somehow
		video.data.tags = [];
		if (fields.tag_list) {
			Ext.each(video.get('tag_list').split(' '), function(t) {
						video.data.tags.push({
									name	: t
								});
					}, this);
		};

		// update the description_html if description is set
		if (fields.description) {
			video.data.description_html = fields.description.replace("\n",
					"<br />"
			);
		};

		video.save({
					url		: this.scopedUrl(String.format(
							"video_albums/{0}/videos/{1}", video
									.get('video_album_id'), video.get('id')
					)),
					scope	: this,
					success	: function() {
						this.fireEvent('update', video);
					}
				});
	},

	/**
	* @action create
	* Creates a new video from the form specified
	*/
	create			: function(form) {
		this.fireEvent('before-update');

		this.indexWindow.showSubmitting();

		var video = new Kohive.models.Video(form.getValues());

		video.save({
					url		: this.scopedUrl(String.format(
							"video_albums/{0}/videos",
							this.currentAlbum[Kohive.OS.getCurrentHiveId()]
									.get('id')
					)),
					scope	: this,
					success	: function() {
						this.indexWindow.closeNewVideoView();
						this.loadAlbumVideos(null, null, true);
						this.fireEvent('update', video);
						this.fireEvent('video-created', video);
					},
					failure	: function() {
						this.indexWindow.showFailure();
					}
				});
	},

	/**
	 * @action destroy 
	 * Destroys the passed video and fires a video-destroyed event
	 * @param {Kohive.models.Video} video The video to destroy
	 */
	destroy			: function(video) {
		video.destroy({
					url		: this.scopedUrl(String.format(
							"video_albums/{0}/videos/{1}.json", video
									.get('video_album_id'), video.get('id')
					)),
					scope	: this,
					success	: function() {
						this.loadAlbumVideos();
						this.fireEvent('video-destroyed', video);
					}
				});
	},

	/**
	 * Filters the currently loaded videos with options from a filter bar
	 * @param {Object} filtersApplied The object of currently applied filters.  Something like:
	 * {authors: [1, 2, 5], tags: ['cat', 'dog']}
	 */
	filter			: function(filters) {
		// for some reason passing the params option to findAll isn't working, so build url manually :/
		var url = this.scopedUrl('video_albums/'
				+ this.currentAlbum[Kohive.OS.getCurrentHiveId()].get('id')
				+ '/videos?'), tags = filters.tags, authors = filters.authors, conditions = [];

		if (tags && tags.length > 0)
			conditions.push(String.format("tags={0}", tags.join(',')));
		if (authors && authors.length > 0)
			conditions.push(String.format("membership_ids={0}", authors
							.join(',')));

		this.loadAlbumVideos(this.currentAlbum[Kohive.OS.getCurrentHiveId()],
				url + conditions.join("&")
		);
	},

	/**
	 * @action show 
	 * Fires an event telling subscriber views to update to the given video
	 * @param {Kohive.models.Video} video The video to show
	 */
	show			: function(video) {
		this.fireEvent('show-video', video);
	},

	/**
	 * @action createAlbum
	 * Creates a new album with the given title argument
	 * @param {String} title The title of the new album to create
	 */
	createAlbum		: function(title) {
		this.fireEvent('before-create-album', title);

		new Kohive.models.VideoAlbum({
					author_membership_id	: Kohive.OS.getCurrentHive()
							.get('id'),
					title					: title
				}).save({
					url		: this.scopedUrl('video_albums'),
					scope	: this,
					success	: function(album) {
						this.fireEvent('album-created', album);
					}
				});
	},

	// /**
	// * @action createRssAlbum
	// * Creates a new rss album with the given feed_url argument
	// * @param {String} feed_url The feed url to fetch the videos from
	// */
	// createRssAlbum: function(feed_url) {
	// this.fireEvent('before-create-album', feed_url);
	//   
	// new Kohive.models.Album({
	// author_membership_id: Kohive.OS.getCurrentHive().get('id'),
	// feed_url: feed_url,
	// type: 'FeedPhotoAlbum'
	// }).save({
	// url: this.scopedUrl('albums'),
	// scope: this,
	// success: function(album) {
	// this.fireEvent('rss-album-created', album);
	// }
	// });
	// },

	/**
	 * @action destroyAlbum
	 * Attempts to destroy an album, fires an album-destroyed event if successful
	 * @param {Kohive.models.Album} album The album to destroy
	 */
	destroyAlbum	: function(album) {
		this.fireEvent('before-destroy-album', album);

		album.destroy({
					url		: this.scopedUrl(String.format("video_albums/{0}",
							album.get('id')
					)),
					scope	: this,
					success	: function() {
						this.fireEvent('album-destroyed', album);
					}
				});
	},

	/**
	 * @action loadAlbumVideos
	 * Loads videos for a specific album and fires the videos-loaded event
	 * @param {Kohive.models.Album} album The album to load videos from
	 * @param {String} url An optional url to use (used by the filter action)
	 * @param {Boolean} newVideo True if it is a new video
	 */
	loadAlbumVideos	: function(album, url, newVideo) {
		var hive = Kohive.OS.getCurrentHive();
		if (!album && !this.currentAlbum[Kohive.OS.getCurrentHiveId()])
			return;
		if (!album && this.currentAlbum[Kohive.OS.getCurrentHiveId()])
			album = this.currentAlbum[Kohive.OS.getCurrentHiveId()];
		this.currentAlbum[Kohive.OS.getCurrentHiveId()] = album;

		this.fireEvent('before-load-videos', album);

		// TODO when creating a new album, it only has a 'title' field, no id. so this must be fixed
		// by returning the id in the response from the server when creating a new album.
		var url = url
				|| this
						.scopedUrl('video_albums/' + album.get('id')
								+ '/videos');

		album.videos.findAll({
					url			: url,
					sortInfo	: {
						field		: 'created_at',
						direction	: 'DESC'
					},
					listeners	: {
						scope	: this,
						load	: function(store) {
							if (store.proxy.conn.url.split('?').length == 1)
								this.originalStore = store.data.items;
							this.currentStore = store;

							this.fireEvent('videos-loaded', store, album);

							var video;
							if (newVideo === true)
								video = store.getAt(0);
							else
								video = store.getAt(0);

							this.fireEvent('show-video', video, newVideo);
						}
					}
				});
	},

	/**
	 * TODO: A hacky method to prepend the /memberships/:membership_id/ segment to the front of an AJAX
	 * request url.  This really ought to be handled by the model, so factor it out of here when possible
	 * @param {String} url The url to append to the memberships scope
	 * @return {String} The fully scoped url
	 */
	scopedUrl		: function(url) {
		return String.format("/memberships/{0}/{1}", Kohive.OS.getCurrentHive()
						.get('id'), url);
	},

	/**
	 * Sets up all of the events this controller emits
	 */
	initEvents		: function() {
		this.addEvents(
				/**
		 * @event before-load-videos
		 * Fires before the request to load (or refresh) videoss from an album is sent
		 */
				'before-load-videos',

				/**
				 * @event videos-loaded
				 * Fired whenever videos for a specific album have been retrieved
				 * @param {Ext.data.Store} videos A store containing videos
				 * @param {Kohive.models.VideoAlbum} album The album that videos were loaded for
				 */
				'videos-loaded',

				/**
				 * @event show-video
				 * Fired whenever subscriber views should update the video they are displaying
				 * @param {Kohive.models.Video} video The new video to display
				 */
				'show-video',

				/**
				 * @event video-destroyed
				 * Fired when a video has been successfully destroyed
				 * @param {Kohive.models.Video} video The video that was destroyed
				 */
				'video-destroyed',

				/**
				 * @event video-created
				 * Fires when a video has been created using a URL
				 */
				'video-created',

				/**
				 * @event before-create-video
				 * Fires before an video is created from a Url
				 */
				'before-create-video',

				/**
				 * @event create-video-failed
				 * Fires when creating an video failed
				 */
				'create-video-failed',

				/**
				 * @event before-update
				 * Fired before an video update request is sent
				 */
				'before-update',

				/**
				 * @event update
				 * Fired when an video has been successful updated
				 * @param {Kohive.models.Video} video The video that was updated
				 */
				'update',

				/**
				 * @event before-create-album
				 * Fires before the request to create an album is sent
				 */
				'before-create-album',

				/**
				 * @event album-created
				 * Fired when a new album has been successfully created
				 * @param {Kohive.models.Album} album The newly created album
				 */
				'album-created',

				/**
				 * @event rss-album-created
				 * Fired when a new rss album has been successfully created
				 * @param {Kohive.models.Album} album The newly created album
				 */
				'rss-album-created',

				/**
				 * @event album-destroyed
				 * Fired when an album has been destroyed
				 * @param {Kohive.models.Album} album The album that was destroyed
				 */
				'album-destroyed'
		);
	},

	/**
	 * Add listeners to the controller
	 */
	initListeners	: function() {
		// this.on('video-created', function() {
		// this.loadAlbumVideos(null, null, true);
		// }, this);
	}

}
);

Kohive.OS.registerController('videos', Kohive.app.VideosController);